﻿#include "cereal/archives/xml.hpp"
#include "cereal/archives/json.hpp"
#include "cereal/archives/binary.hpp"

#include "cereal/types/unordered_map.hpp"
#include "cereal/types/memory.hpp"


#include <fstream>

// struct MyClass
// {
//   int x, y, z;

//   // This method lets cereal know which data members to serialize
//   template<class Archive>
//   void serialize(Archive & archive)
//   {
//     archive( x, y, z ); // serialize things by passing them to the archive
//   }
// };

struct MyRecord
{
  uint8_t x, y;
  float z;

  template <class Archive>
  void serialize(Archive &ar)
  {
    ar(x, y, z);
  }
};

struct SomeData
{
  int32_t id;
  std::shared_ptr<std::unordered_map<uint32_t, MyRecord>> data;

  template <class Archive>
  void save(Archive &ar) const
  {
    ar(data);
  }

  template <class Archive>
  void load(Archive &ar)
  {
    static int32_t idGen = 0;
    id = idGen++;
    ar(data);
  }
};

struct MyData
{
  int x, y, z;

  // 定义序列化函数
  template <class Archive>
  void serialize(Archive &archive)
  {
    archive(CEREAL_NVP(y), CEREAL_NVP(x), CEREAL_NVP(z)); // serialize things by passing them to the archive
  }
};

int main()
{
  //for json
  {
    {
    std::ofstream os("data.json");
    cereal::JSONOutputArchive archive(os);

    MyData m1;
    m1.x = 12;
    m1.y = 13;
    m1.z = 14;
    int someInt;
    double d;

    archive(CEREAL_NVP(m1),                                  // Names the output the same as the variable name
            someInt,                                         // No NVP - cereal will automatically generate an enumerated name
            cereal::make_nvp("this_name_is_way_better", d)); // specify a name of your choosing
  }

  {
    std::ifstream is("data.json");
    cereal::JSONInputArchive archive(is);

    MyData m1;
    int someInt;
    double d;

    archive(m1, someInt, d); // NVPs not strictly necessary when loading
                             // but could be used (even out of order)
  }
  }

  //for xml
  {
    {// **注意这列大括号的作用**，大括号之外析构归档对象，将归档数据写进对应文档中
    std::ofstream os("data.xml");
    cereal::XMLOutputArchive archive(os);

    MyData m1;
    int someInt;
    double d;

    archive( CEREAL_NVP(m1), // 序列化变量 m1 时使用变量的原始名称 'm1'
             someInt,        // cereal 将自动为 someInt 定义一个名字
             // 序列化变量 d 时，使用用户自定义的名字
             cereal::make_nvp("this_name_is_way_better", d) );
  }// 析构 archive，将数据写进 os 中

  {
    std::ifstream is("data.xml");
    cereal::XMLInputArchive archive(is);
    
    MyData m1;
    int someInt;
    double d;
    // 反序列化过程不需要指定变量名，也可以指定
    archive( m1, someInt, d );
  }
  }

  {
    std::ofstream os("out.cereal", std::ios::binary);
    cereal::BinaryOutputArchive archive(os);

    SomeData myData;
    archive(myData);
  }
}